#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <U8g2lib.h>  // 替换Adafruit库，使用U8g2支持中文

// 新增串口读取超时控制
#define SERIAL_READ_TIMEOUT 1000  // 毫秒1s
#define MAX_BUFFER_SIZE 512      // 与Python的512保持一致

// LCD配置 - 0.96英寸OLED (SSD1306驱动)
#define SDA_PIN 14  // D6
#define SCL_PIN 12  // D5
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, SCL_PIN, SDA_PIN);  // U8g2初始化

// WiFi配置
const char* ssid = "hgsy"; // 替换为实际WiFi名称
const char* password = "hg111111"; // 替换为实际WiFi密码

// MQTT配置
const char* mqtt_server = "192.168.1.222"; // MQTT服务器IP
const int mqtt_port = 1883; // MQTT服务器端口
const char* mqtt_topic = "bms48200/data/home"; // 发布主题
const char* clientId = "ESP8266_BMS_Client-home"; //传递客户端ID

WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastSendTime = 0; // 记录上次发送指令时间
const unsigned long sendInterval = 5000; // 发送间隔（5秒）

//const char* command = "~200046F2E00201FD24\r"; // 发送给公司BMS的指令
// 发送给家BMS的指令
const char* command = "~21004642E00200FD36\r";

void setup() {
    Serial.begin(9600); // 初始化串口，与BMS波特率一致（9600,8,1）
    Serial.println("\n[SETUP] 开始初始化...");
    
    // 初始化OLED显示
    u8g2.begin();
    u8g2.clearBuffer();
    
    // 设置中文字体（16x16像素，放大一倍）
    u8g2.setFont(u8g2_font_wqy12_t_gb2312);
    u8g2.setFontMode(1); // 反白模式
    
    // 显示初始化信息
    showLCD("[SETUP] 初始化中...", 0);
    showLCD("[WIFI] 连接中...", 20);
    u8g2.sendBuffer();
    
    // 连接WiFi
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
        Serial.println("[WIFI] 连接中...");
    }
    Serial.println("\n[WIFI] 连接成功");
    showLCD("[WIFI] OK", 20);
    
    client.setServer(mqtt_server, mqtt_port);
    client.setCallback(callback); // 设置MQTT回调函数
    lastSendTime = millis(); // 记录当前时间
    
    // 尝试连接MQTT服务器
    reconnect();
}

void loop() {
    if (WiFi.status() != WL_CONNECTED) {
        WiFi.begin(ssid, password); // 重连WIFI
    }
    if (!client.connected()) {
        reconnect(); // 重连MQTT
    }
    client.loop();
    
    // 定时发送指令
    if (millis() - lastSendTime >= sendInterval) {
        Serial.print(command); // 发送指令到串口
        lastSendTime = millis(); // 更新发送时间
        
        // 阻塞读取串口数据
        String serialData = readSerialLikePython();
        
        // 若有数据，发布到MQTT并显示
        if (serialData.length() > 0) {
            Serial.println("[DATA] 接收到数据: ");
            Serial.println(serialData);
            showLCD("[DATA] Received", 0);
            showLCD(serialData, 20);
            
            if (client.publish(mqtt_topic, serialData.c_str())) {
                Serial.println("[MQTT] 数据发布成功");
                showLCD("[MQTT] PUB OK", 40);
                delay(1000);
            } else {
                Serial.println("[MQTT] 数据发布失败");
                showLCD("[MQTT] Pub lost", 40);
                delay(1000);
            }
        }
    }
}

// MQTT回调函数
void callback(char* topic, byte* payload, unsigned int length) {
    Serial.println("[MQTT CALLBACK] 收到消息，主题: ");
    Serial.println(topic);
    showLCD("[MQTT CALLBACK] 收消息", 0);
    showLCD(topic, 20);
    
    String payloadStr;
    for (unsigned int i = 0; i < length; i++) {
        Serial.println((char)payload[i]);
        payloadStr += (char)payload[i];
    }
    Serial.println();
    showLCD(payloadStr, 40);
}

String readSerialLikePython() {
  String data;
  unsigned long startTime = millis();
  
  while ((millis() - startTime) < SERIAL_READ_TIMEOUT) {
    if (Serial.available() > 0) {
      char c = Serial.read();
      data += c;
      if (data.length() >= MAX_BUFFER_SIZE) {
        break;  // 达到最大读取量
      }
    }
  }
  return data;
}

// 重连MQTT函数
void reconnect() {
    while (!client.connected()) {
        Serial.println("[MQTT] try to server...");
        showLCD("[MQTT] try to server...", 0);
        
        if (client.connect("clientId")) {
            Serial.println("连接成功！");
            showLCD("[MQTT] Link OK！", 0);
        } else {
            Serial.println("连接失败，状态码: ");
            Serial.println(client.state());
            Serial.println(" 重试中...");
            showLCD("[MQTT] Link Lose", 0);
            showLCD("状态码: " + String(client.state()), 20);
            showLCD("5S后重试...", 40);
        }
        delay(5000); // 等待5秒后重试
    }
}

// 更新LCD显示的辅助函数（修复重叠问题）
void showLCD(String message, int lineIndex) {
    u8g2.clearBuffer(); // 清屏
    
    // 显示WiFi状态（小字体）
    u8g2.setFont(u8g2_font_6x10_tf);
    u8g2.setCursor(0, 10);
    u8g2.println("[WiFi] ");
    u8g2.println(WiFi.localIP().toString());
    
    // 定义每行的垂直位置（基于16像素字体高度）
    const int lineYPos[] = {24, 38, 52}; // 每行间隔18像素（16+2留白）
    const int maxLines = 3; // 最多显示3行主信息
    
    if (lineIndex < maxLines) {
        // 显示主消息（16x16字体）
        u8g2.setFont(u8g2_font_wqy12_t_gb2312);
        u8g2.setCursor(0, lineYPos[lineIndex]);
        u8g2.println(message);
    }
    
    // 显示时间（小字体）
    u8g2.setFont(u8g2_font_6x10_tf);
    unsigned long currentTime = millis() / 1000;
    u8g2.setCursor(0, 60);
    u8g2.println("time: ");
    u8g2.println(currentTime);
    u8g2.println("s");
    
    u8g2.sendBuffer();
}